package com.zw.utils.encrypt;

import java.math.BigInteger;
import java.util.Random;

public class PaillierAlgorithm {
    private BigInteger n;
    private BigInteger g;
    private BigInteger lambda;
    private BigInteger mu;

    public PaillierAlgorithm() {
        Random rng = new Random();
        // 生成两个大素数 p 和 q
        BigInteger p = BigInteger.probablePrime(100, rng);
        BigInteger q = BigInteger.probablePrime(100, rng);
        n = p.multiply(q);
        BigInteger nSquare = n.multiply(n);
        g = n.add(BigInteger.ONE); // 选择合适的 g
        lambda = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE)); // 计算 λ
        mu = lambda.modInverse(n); // 计算 μ
    }

    // Paillier 加密
    public BigInteger encrypt(BigInteger plaintext) {
        Random rng = new Random();
        BigInteger r = new BigInteger(n.bitLength(), rng);
        BigInteger nSquare = n.multiply(n);
        return g.modPow(plaintext, nSquare)
                .multiply(r.modPow(n, nSquare))
                .mod(nSquare);
    }

    // Paillier 解密
    public BigInteger decrypt(BigInteger ciphertext) {
        BigInteger nSquare = n.multiply(n);
        BigInteger u = ciphertext.modPow(lambda, nSquare);
        BigInteger lResult = u.subtract(BigInteger.ONE).divide(n);
        return lResult.multiply(mu).mod(n);
    }

    // Paillier 加法同态：密文相加（实际是密文相乘）
    public BigInteger addHomomorphic(BigInteger ciphertext1, BigInteger ciphertext2) {
        BigInteger nSquare = n.multiply(n);
        return ciphertext1.multiply(ciphertext2).mod(nSquare);
    }
}
